package dao

import (
	"collection_srv/model"
	"context"
	"encoding/json"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/zeromicro/go-zero/core/logx"
	"go.mongodb.org/mongo-driver/bson"
	"go.uber.org/zap"
	"log"
	"math/rand"
	"os"
	"os/signal"
	"smart-health-platforms/config"
	"smart-health-platforms/inits"
	"smart-health-platforms/pkg"
	"strconv"
	"syscall"
	"time"
)

// 温度计发送数据
func TSendData(DeviceId, UserId uint64, result *model.ThermometerData) {
	inits.Configuration()
	config.Opts.SetClientID("temperature-publisher")
	client := mqtt.NewClient(config.Opts)
	if token := client.Connect(); token.Wait() && token.Error() != nil {
		logx.Errorf("连接EMQX失败: %v", nil)
	}
	// 处理退出信号
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
	// 设置1分钟超时

	// 创建定时器，每3秒发布一次数据
	ticker := time.NewTicker(3 * time.Second)
	defer ticker.Stop()
	// 主循环

	//随机生成30.0到40.0的随机数
	min1 := 30.0
	max1 := 40.0
	randomFloatRange := min1 + rand.Float64()*(max1-min1)
	// 设置体温数据
	result.DeviceId = DeviceId
	result.UserId = UserId
	result.CollectionTime = strconv.FormatInt(time.Now().Unix(), 10)
	result.Result = float32(randomFloatRange) // 生成30-39的随机数
	data := model.ThermometerData{
		DeviceId:       result.DeviceId,
		UserId:         result.UserId,
		CollectionTime: result.CollectionTime,
		Result:         result.Result, //  使用最后生成的体温值30.0-39.9
	}

	// 序列化数据
	payload, err := json.Marshal(data)
	if err != nil {
		logx.Errorf("数据序列化失败: %v", err)

	}
	// 发布数据到MQTT主题
	if token := client.Publish("sensors/temperature", 1, false, payload); token.Wait() && token.Error() != nil {
		logx.Errorf("[发布者]发送消息失败: %v", token.Error())
	} else {
		logx.Infof("\n[发布者]发送数据: %.1f °C 到主题: sensors/temperature", data.Result)
	}
}

// 温度计消息回调
func TMessageCallback(DeviceId, UserId uint64, result *model.ThermometerData) {

	//连接到EMQX服务器，订阅主题
	client := mqtt.NewClient(config.Opts)
	if token := client.Connect(); token.Wait() && token.Error() != nil {
		logx.Errorf("连接EMQX失败: %v", nil)
	}
	log.Println("[订阅者] 连接EMQX成功")
	messageHandler := func(client mqtt.Client, msg mqtt.Message) {

		// 解析MQTT消息
		if err := json.Unmarshal(msg.Payload(), &result); err != nil {
			logx.Errorf("解析消息失败: %v", err)
			return
		}
		// 处理接收到的消息
		logx.Infof("收到消息: %+v", result)
		// 这里添加您的业务逻辑
	}
	inits.SuccessMessageCallback(messageHandler)
	//清洗数据
	stdData, err := ThermometerClean(result.CollectionTime, result.Result, "C")
	if err != nil {
		// 2. 清洗失败（数据异常）：不执行存储，仅记录日志
		pkg.Warn("体温数据异常，不存入MongoDB", zap.Error(err), zap.Any("原始数据", result.Result))
		return // 可根据需要返回错误或忽略
	}
	// 使用清洗后的数据
	result.Result = float32(stdData.MeasureValue)
	result.DeviceId = DeviceId
	result.UserId = UserId
	result.CollectionTime = strconv.FormatInt(time.Now().Unix(), 10)
	collection := config.HealthDB.Collection("result_data")
	if err := inits.InitCounter("result_data"); err != nil {
		logx.Error("计数器初始化失败", zap.Error(err))
		return
	}
	// 2. 获取下一个自增 ID
	seq, err := inits.GetNextID("result_data")
	if err != nil {
		logx.Error("获取自增 ID 失败", zap.Error(err))
		return
	}
	// 3. 插入数据（用自增 ID 作为 _id）
	_, err = collection.InsertOne(context.Background(), bson.M{
		"_id":             seq, // 自增 ID
		"device_id":       result.DeviceId,
		"user_id":         result.UserId,
		"collection_time": result.CollectionTime,
		"result":          result.Result,
		"data_type":       "result",
		"cleaned":         true,
	})
	if err != nil {
		logx.Error("插入失败", zap.Error(err))
		return
	}
	// 记录处理成功的日志
	logx.Infof("收到数据 - 设备ID: %v,用户ID: %v, 温度值: %.1f °C, 时间: %v",
		result.DeviceId, result.UserId, result.Result, result.CollectionTime)
}

// 心跳检查发送数据
func OSendData(DeviceId, UserId uint64, result *model.BloodPressure) {
	inits.Configuration()
	config.Opts.SetClientID("temperature-publisher")
	client := mqtt.NewClient(config.Opts)
	if token := client.Connect(); token.Wait() && token.Error() != nil {
		logx.Errorf("连接EMQX失败: %v", nil)
	}

	//随机生成50.0到130.0的随机数
	min1 := 50.0
	max1 := 130.0
	randomFloatRange := min1 + rand.Float64()*(max1-min1)
	// 设置心跳数据
	result.DeviceId = DeviceId
	result.UserId = UserId
	result.CollectionTime = strconv.FormatInt(time.Now().Unix(), 10)
	result.Result = float32(randomFloatRange) // 生成50.0-130.0的随机数
	data := model.ThermometerData{
		DeviceId:       result.DeviceId,
		UserId:         result.UserId,
		CollectionTime: result.CollectionTime,
		Result:         result.Result, // 90.0-130.0
	}
	payload, err := json.Marshal(data)
	if err != nil {
		logx.Errorf("数据序列化失败: %v", err)

	}
	if token := client.Publish("sensors/temperature", 1, false, payload); token.Wait() && token.Error() != nil {
		logx.Errorf("发送消息失败: %v", token.Error())
	} else {
		logx.Infof("发送数据: %.1f  到主题: sensors/temperature", data.Result)
	}

}

// 心跳检查消息回调
func OMessageCallback(DeviceId, UserId uint64, result *model.BloodPressure) {
	//连接到EMQX服务器，订阅主题
	client := mqtt.NewClient(config.Opts)
	if token := client.Connect(); token.Wait() && token.Error() != nil {
		logx.Errorf("连接EMQX失败: %v", nil)
	}
	log.Println("[订阅者] 连接EMQX成功")
	messageHandler := func(client mqtt.Client, msg mqtt.Message) {

		// 解析MQTT消息
		if err := json.Unmarshal(msg.Payload(), &result); err != nil {
			logx.Errorf("解析消息失败: %v", err)
			return
		}
		// 处理接收到的消息
		logx.Infof("收到消息: %+v", result)
		// 这里添加您的业务逻辑
	}
	inits.SuccessMessageCallback(messageHandler)
	// 清洗数据
	cleanedTemp, err := OximeterClean(result.CollectionTime, result.Result, "")
	if err != nil {
		// 2. 清洗失败（数据异常）：不执行存储，仅记录日志
		pkg.Warn("心跳数据异常，不存入MongoDB", zap.Error(err), zap.Any("原始数据", result.Result))
		return // 可根据需要返回错误或忽略
	}
	// 使用清洗后的数据
	result.Result = float32(cleanedTemp.MeasureValue)
	result.DeviceId = DeviceId
	result.UserId = UserId
	result.CollectionTime = strconv.FormatInt(time.Now().Unix(), 10)
	collection := config.HealthDB.Collection("heartbeat_data")
	if err := inits.InitCounter("heartbeat_data"); err != nil {
		logx.Error("计数器初始化失败", zap.Error(err))
		return
	}
	// 2. 获取下一个自增 ID
	seq, err := inits.GetNextID("heartbeat_data")
	if err != nil {
		logx.Error("获取自增 ID 失败", zap.Error(err))
		return
	}
	// 3. 插入数据（用自增 ID 作为 _id）
	_, err = collection.InsertOne(context.Background(), bson.M{
		"_id":             seq, // 自增 ID
		"device_id":       result.DeviceId,
		"user_id":         result.UserId,
		"collection_time": result.CollectionTime,
		"result":          result.Result,
		"data_type":       "heartbeat",
		"cleaned":         true,
	})
	if err != nil {
		logx.Error("插入失败", zap.Error(err))
		return
	}
	logx.Infof("收到数据 - 设备ID: %v,用户ID: %v, 心跳值: %.1f , 时间: %v",
		result.DeviceId, result.UserId, result.Result, result.CollectionTime)

}

// 血糖检查发送数据
func GSendData(DeviceId, UserId uint64, result *model.BloodGlucoseMeterData) {
	inits.Configuration()
	config.Opts.SetClientID("temperature-publisher")
	client := mqtt.NewClient(config.Opts)
	if token := client.Connect(); token.Wait() && token.Error() != nil {
		logx.Errorf("连接EMQX失败: %v", nil)
	}
	//随机生成3.0到6.0的随机数
	min1 := 3.0
	max1 := 6.0
	randomFloatRange := min1 + rand.Float64()*(max1-min1)
	result.DeviceId = DeviceId
	result.UserId = UserId
	result.CollectionTime = strconv.FormatInt(time.Now().Unix(), 10)
	result.Result = float32(randomFloatRange) // 生成3.0-6.0的随机数
	data := model.ThermometerData{
		DeviceId:       DeviceId,
		UserId:         UserId,
		CollectionTime: strconv.FormatInt(time.Now().Unix(), 10),
		Result:         result.Result, // 30.0-39.9
	}

	payload, err := json.Marshal(data)
	if err != nil {
		logx.Errorf("数据序列化失败: %v", err)

	}

	if token := client.Publish("sensors/temperature", 1, false, payload); token.Wait() && token.Error() != nil {
		logx.Errorf("发送消息失败: %v", token.Error())
	} else {
		logx.Infof("发送数据: %.1f  到主题: sensors/temperature", data.Result)
	}
}

// 血糖检查消息回调
func GMessageCallback(DeviceId, UserId uint64, result *model.BloodGlucoseMeterData) {
	//连接到EMQX服务器，订阅主题
	client := mqtt.NewClient(config.Opts)
	if token := client.Connect(); token.Wait() && token.Error() != nil {
		logx.Errorf("连接EMQX失败: %v", nil)
	}
	log.Println("[订阅者] 连接EMQX成功")
	messageHandler := func(client mqtt.Client, msg mqtt.Message) {

		// 解析MQTT消息
		if err := json.Unmarshal(msg.Payload(), &result); err != nil {
			logx.Errorf("解析消息失败: %v", err)
			return
		}
		// 处理接收到的消息
		logx.Infof("收到消息: %+v", result)
		// 这里添加您的业务逻辑
	}
	inits.SuccessMessageCallback(messageHandler)
	// 清洗数据
	cleanedTemp, err := GlucoseClean(result.CollectionTime, result.Result, "")
	if err != nil {
		// 2. 清洗失败（数据异常）：不执行存储，仅记录日志
		pkg.Warn("血糖数据异常，不存入MongoDB", zap.Error(err), zap.Any("原始数据", result.Result))
		return // 可根据需要返回错误或忽略
	}
	// 使用清洗后的数据
	result.Result = float32(cleanedTemp.MeasureValue)
	result.DeviceId = DeviceId
	result.UserId = UserId
	result.CollectionTime = strconv.FormatInt(time.Now().Unix(), 10)
	collection := config.HealthDB.Collection("glucose_data")
	if err := inits.InitCounter("glucose_data"); err != nil {
		logx.Error("计数器初始化失败", zap.Error(err))
		return
	}
	// 2. 获取下一个自增 ID
	seq, err := inits.GetNextID("glucose_data")
	if err != nil {
		logx.Error("获取自增 ID 失败", zap.Error(err))
		return
	}
	// 3. 插入数据（用自增 ID 作为 _id）
	_, err = collection.InsertOne(context.Background(), bson.M{
		"_id":             seq, // 自增 ID
		"device_id":       result.DeviceId,
		"user_id":         result.UserId,
		"collection_time": result.CollectionTime,
		"result":          result.Result,
		"data_type":       "glucose",
		"cleaned":         true,
	})
	if err != nil {
		logx.Error("插入失败", zap.Error(err))
		return
	}
	logx.Infof("收到数据 - 设备ID: %v,用户ID: %v, 空腹血糖值: %.1f °C, 时间: %v",
		result.DeviceId, result.UserId, result.Result, result.CollectionTime)
}
